package org.genitus.druidry

import in.zapr.druid.druidry.Interval
import in.zapr.druid.druidry.granularity.{DurationGranularity, Granularity, PeriodGranularity, SimpleGranularity}
import org.joda.time.{DateTime, DateTimeZone, Period}

import scala.collection.JavaConversions._

object EmptyFilling {
  def timeseriesFill[E<:DruidTimeseriesResult](intervals: List[Interval], granularity: Granularity, druidResponse: List[DruidTimeseriesResponse[E]]):List[DruidTimeseriesResponse[E]] = {
    /** 获取druid granularity 用于后续取 bucket*/
    val druidGranularity:io.druid.java.util.common.granularity.Granularity = covertGranularity(granularity)

    /** 根据Interval 和 granularity进行 bucket分割,将多个Intevals结果展平、去重、排序，生成empty result 数据*/
    val fillResponse:List[DruidTimeseriesResponse[E]] = intervals.flatMap(interval => {
      getBucketFromInterval(druidGranularity,interval)
    }).distinct
      .sortWith((left,right) => left.isBefore(right))
      .map(dateTime => new DruidTimeseriesResponse[E](dateTime))

    /** 真实数据变为map，遍历取值合并到填充List中*/
    val druidResponeMap =  druidResponse.map(x => (x.timestamp,x)).toMap
    fillResponse.map(x=> druidResponeMap.getOrDefault(x.timestamp,x))
  }

  /**
    * 将 Druidry granularity 转换成 Druid granularity，因为获取bucket的函数在Druid granularity中
    * @param granularity Druidry granularity
    * @return Druid granularity
    */
  def covertGranularity(granularity: Granularity):io.druid.java.util.common.granularity.Granularity = {
    granularity match {
      case  periodGranularity: PeriodGranularity =>
        new io.druid.java.util.common.granularity.PeriodGranularity(
          Period.parse(periodGranularity.getPeriod),
          new DateTime(periodGranularity.getOrigin),
          DateTimeZone.forID(periodGranularity.getTimeZone)
        )

      case simpleGranularity: SimpleGranularity =>
        io.druid.java.util.common.granularity.GranularityType
          .valueOf(simpleGranularity.getGranularity.getPredefinedGranularityString)
          .getDefaultGranularity


      case durationGranularity:DurationGranularity =>
        new io.druid.java.util.common.granularity.DurationGranularity(
          durationGranularity.getDurationInMilliSeconds,
          new DateTime(durationGranularity.getOrigin)
        )
    }
  }

  /**
    * 在时间周期内根据 druid granularity 划分bucket
    * @param granularity  Druid granularity
    * @param interval     Druidry Interval
    * @return             一系列的时间点，相邻的组成一个桶
    */
  def getBucketFromInterval(granularity: io.druid.java.util.common.granularity.Granularity,interval: Interval):List[DateTime] = {
    granularity.getIterable(
      new org.joda.time.Interval(interval.getStartTime,interval.getEndTime)
    ).toList.map(x => x.getStart)
  }







}
